package bookmarks;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.util.Collection;
import java.util.Optional;
import java.net.URI;


@RestController
@RequestMapping("/{userId}/bookmarks")
public class BookmarkRestController {
    private final AccountRepository accountRepository;
    private final BookMarkRepository bookmarkRepository;

    @Autowired
    BookmarkRestController(AccountRepository accountRepository, BookMarkRepository bookmarkRepository) {
        this.accountRepository = accountRepository;
        this.bookmarkRepository = bookmarkRepository;
    }

    @RequestMapping(method = RequestMethod.GET)
    Collection<BookMark> readBookmarks(@PathVariable String userId) throws Exception {
        this.validateUser(userId);
        return this.bookmarkRepository.findByAccountUsername(userId);
    }

    @RequestMapping(method = RequestMethod.POST)
    ResponseEntity<?> add(@PathVariable String userId, @RequestBody BookMark input) throws Exception {
        this.validateUser(userId);

        return this.accountRepository.findByUsername(userId).map(account -> {
            final Optional<BookMark> savedBookmark = bookmarkRepository.save(new BookMark(account, input.getUri(), input.getDescription()));
            return savedBookmark.map(bookmark -> {
                URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(bookmark.getId()).toUri();
                return ResponseEntity.created(location).build();
            })
            .orElse(ResponseEntity.noContent().build());
        })
        .orElse(ResponseEntity.noContent().build());
    }

    @RequestMapping(method = RequestMethod.GET, value = "/{bookmarkId}")
    BookMark readBookmark(@PathVariable String userId, @PathVariable Long bookmarkId) throws Exception {
        this.validateUser(userId);
        return this.bookmarkRepository.findById(bookmarkId).map(x -> x).orElseThrow(
            () -> new BookmarkNotFoundException(bookmarkId));
    }

    private void validateUser(String userId) throws Exception {
        this.accountRepository.findByUsername(userId).orElseThrow(
            () -> new UserNotFoundException(userId));
    }

}
